#include <all_lib.h>
#pragma hdrstop
#if defined(__MYPACKAGE__)
#pragma package(smart_init)
#endif

/*******************************************************************
   Crc32

 [mu_crc32.cpp]

   Generate 32bit CRC for buffer.

   Algoriphm getted from sources of ZLib.
 *******************************************************************/

static int   crc_table_empty = 1;
static DWORD crc_table[256];

static void make_crc_table( void )
{
  DWORD c;
  int n, k;
  DWORD poly;            /* polynomial exclusive-or pattern */
  /* terms of polynomial defining this crc (except x^32): */
  static const BYTE p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26};

  /* make exclusive-or pattern from polynomial (0xedb88320L) */
  poly = 0L;
  for (n = 0; n < sizeof(p)/sizeof(BYTE); n++)
    poly |= 1L << (31 - p[n]);

  for (n = 0; n < 256; n++)
  {
    c = (DWORD)n;
    for (k = 0; k < 8; k++)
      c = c & 1 ? poly ^ (c >> 1) : c >> 1;
    crc_table[n] = c;
  }
  crc_table_empty = 0;
}

/* ========================================================================= */
#define DO1(buf)  crc = crc_table[((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8);
#define DO2(buf)  DO1(buf); DO1(buf);
#define DO4(buf)  DO2(buf); DO2(buf);
#define DO8(buf)  DO4(buf); DO4(buf);

DWORD MYRTLEXP Crc32( DWORD crc, CONSTSTR buf )
  {
 return Crc32( crc, (LPCBYTE)buf, strLen(buf) );
}

DWORD MYRTLEXP Crc32( DWORD crc, LPCBYTE buf,DWORD len )
  {
    if ( buf == NULL )
      return 0L;

    if (crc_table_empty)
      make_crc_table();

    crc = crc ^ 0xffffffffL;

    while (len >= 8) {
      DO8(buf);
      len -= 8;
    }
    if (len)
      do{
        DO1(buf);
      }while (--len);

 return crc ^ 0xffffffffL;
}
